<?php
// +----------------------------------------------------------------------
// | 个推
// +----------------------------------------------------------------------

namespace helper\getui;


class Getui implements Driver
{
    private $baseUrl;

    private $config;

    private $header;

    private $title;

    private $body;

    private $click_type;

    private $option = [];

    public function __construct($config)
    {
        $this->config  = [
            'appId'        => $config['app_id'],
            'appKey'       => $config['app_key'],
            'masterSecret' => $config['master_secret'],
            'appName'      => $config['app_name'],
        ];
        $this->baseUrl = 'https://restapi.getui.com/v2/' . $this->config['appId'];
    }

    public function header($token)
    {
        $this->header = [
            'content-type:application/json;charset=utf-8',
            'token:' . $token
        ];
        return $this;
    }

    /**
     * 鉴权
     */
    public function auth()
    {
        $url          = $this->baseUrl . '/auth';
        $appKey       = $this->config['appKey'];
        $masterSecret = $this->config['masterSecret'];
        $timestamp    = $this->getMicroTime();
        $params       = [
            "sign"      => hash("sha256", $appKey . $timestamp . $masterSecret),
            "timestamp" => $timestamp,
            "appkey"    => $appKey
        ];
        $response     = $this->request('POST', $url, ['json' => $params, 'headers' => ['content-type:application/json;charset=utf-8']]);
        return $response['body']['data']['token'];
    }

    /**
     * cid
     * @param array $cid
     * @return $this
     */
    public function setCid(array $cid): Getui
    {
        $option["audience"] = [
            "cid" => $cid
        ];
        $this->option = array_merge($this->option, $option);
        return $this;
    }

    /**
     * request_id
     * @param $request_id
     * @return $this
     */
    public function setRequestId($request_id): Getui
    {
        $option["request_id"] = $request_id;;
        $this->option = array_merge($this->option, $option);
        return $this;
    }

    /**
     * 消息离线时间
     * @param int $ttl
     * @return $this
     */
    public function setSettings(int $ttl = 3600000): Getui
    {
        $option["settings"] = [
            "ttl" => $ttl
        ];
        $this->option = array_merge($this->option, $option);
        return $this;
    }

    /**
     * 任务组名
     * @param string $group_name
     * @return $this
     */
    public function setGroupName(string $group_name): Getui
    {
        $option["group_name"] = $group_name;
        $this->option = array_merge($this->option, $option);
        return $this;
    }

    /**
     * 标题
     * @param string $title
     * @return $this
     */
    public function setTitle(string $title): Getui
    {
        $this->title = $title;
        return $this;
    }

    /**
     * 内容
     * @param string $body
     * @return $this
     */
    public function setBody(string $body): Getui
    {
        $this->body = $body;
        return $this;
    }

    /**
     *
     * @param string $key
     * @param string $value
     * @return $this
     */
    public function setClickType(string $key = 'payload', string $value = ''): Getui
    {
        $this->click_type = ['key' => $key, 'value' => $value];
        return $this;
    }

    /**
     * 推送目标用户
     * @param string $tag
     * @return $this
     */
    public function setAudience(string $tag = ''): Getui
    {
        $option["audience"] = $tag ? ['fast_custom_tag' => $tag] : 'all';
        $this->option = array_merge($this->option, $option);
        return $this;
    }

    /**
     * 个推推送消息参数
     * @return $this
     */
    public function setPushMessage(): Getui
    {
        $option['push_message'] = [
            // 通知消息
            "notification" => [
                "title"                  => $this->title,
                "body"                   => $this->body,
                "click_type"             => $this->click_type['key'],
                $this->click_type['key'] => $this->click_type['value'],
            ],
            // 透传消息
            // "transmission" => "{title:$title,content:$body,payload:$payload}",
            // 撤回消息
            // "revoke" => []
        ];
        $this->option = array_merge($this->option, $option);
        return $this;
    }

    /**
     * 厂商推送消息参数
     * @return $this
     */
    public function setPushChannel(): Getui
    {
        $option['push_channel'] = [
            "android" => [
                "ups" => [
                    "notification" => [
                        "title"      => $this->title,
                        "body"       => $this->body,
                        "click_type" => "intent",//intent,url,payload,payload_custom,startapp,none
                        "intent"     => "intent:#Intent;action=android.intent.action.oppopush;launchFlags=0x14000000;component={$this->config['appName']}/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=$this->title;S.content=$this->body;S.{$this->click_type['key']}={$this->click_type['value']};end"
                    ],
                    "options"      => [
                        "XM" => [
                            "channel" => "high_system"
                        ],
                    ]
                ]
            ],
            "ios"     => [
                "type"                   => "notify",
                $this->click_type['key'] => $this->click_type['value'],
                "aps"                    => [
                    "alert"             => [
                        "title" => $this->title,
                        "body"  => $this->body
                    ],
                    "content-available" => 0
                ],
                "auto_badge"             => "+1"
            ]
        ];
        $this->option = array_merge($this->option, $option);
        return $this;
    }



    /**
     * 单推
     * @return mixed
     */
    public function single()
    {
        $url      = $this->baseUrl . '/push/single/cid';
        $keys     = ['request_id', 'settings', 'audience', 'push_message', 'push_channel'];
        $response = $this->request('POST', $url, ['json' => $this->option, 'headers' => $this->header]);
        return $response['body'];
    }

    /**
     * 创建消息
     */
    private function message()
    {
        $url      = $this->baseUrl . '/push/list/message';
        $keys     = ['request_id', 'settings', 'group_name', 'push_message', 'push_channel'];
        $response = $this->request('POST', $url, ['json' => $this->option, 'headers' => $this->header]);
        if ($response['body']['code'] == 0) {
            return $response['body']['data']['taskid'];
        }
        return '';
    }

    /**
     * 批量推
     */
    public function list()
    {
        $url                = $this->baseUrl . '/push/list/cid';
        $option['audience'] = $this->option['audience'];
        $option['taskid']   = $this->message();
        $option['is_async'] = true;
        $keys               = ['audience', 'taskid', 'is_async'];
        $response           = $this->request('POST', $url, ['json' => $option, 'headers' => $this->header]);
        return $response['body'];
    }

    /**
     * 群推
     * @return mixed
     */
    public function app()
    {
        $url      = $this->baseUrl . '/push/';

        // 1) 群推
        if (!is_array($this->option['audience'])) {
            $url = $url . 'all';
        } else {
            // 2) 标签筛选
            if (isset($this->option['audience']['tag'])) {
                $url = $url . 'tag';
            } else {
                // 3) 标签快速
                $url = $url . 'fast_custom_tag';
            }
        }
        $keys     = ['request_id', 'settings', 'group_name', 'audience', 'push_message', 'push_channel'];
        $response = $this->request('POST', $url, ['json' => $this->option, 'headers' => $this->header]);
        return $response['body'];
    }

    /**
     * 查询用户信息
     * @param $cid
     * @return mixed
     */
    public function user($cid)
    {
        $url      = $this->baseUrl . '/user/detail/' . $cid;
        $response = $this->request('GET', $url, ['headers' => $this->header]);
        return $response['body'];
    }

    /**
     * 绑定别名
     * 一个cid只能绑定一个别名,一个别名最多允许绑定10个cid
     */
    public function alias($cid, $alias)
    {
        $url      = $this->baseUrl . '/user/alias';
        $params   = [
            "data_list" => [
                [
                    "cid"   => $cid,
                    "alias" => $alias,
                ]
            ],
        ];
        $response = $this->request('POST', $url, ['json' => $params, 'headers' => $this->header]);
        return $response['body'];
    }

    /**
     * 查询用户标签
     * @param string $cid
     * @return mixed
     */
    public function getCustomTag(string $cid)
    {
        $url      = $this->baseUrl . '/user/custom_tag/cid/' . $cid;
        $response = $this->request('GET', $url, ['headers' => $this->header]);
        return $response['body'];
    }

    /**
     * 一个用户绑定一批标签
     * @param string $cid
     * @param array $tag
     */
    public function setCustomTag(string $cid, array $tag)
    {
        $url      = $this->baseUrl . '/user/custom_tag/cid/' . $cid;
        $params   = [
            "custom_tag" => $tag,
        ];
        $response = $this->request('POST', $url, ['json' => $params, 'headers' => $this->header]);
        return $response['body'];
    }

    private function getMicroTime()
    {
        list($usec, $sec) = explode(" ", microtime());
        return $sec . substr($usec, 2, 3);
    }

    /**
     * 发起请求 string $method, $uri = '', array $options = []
     * @param string $method
     * @param string $url
     * @param array $options
     * @return array
     */
    private function request(string $method, string $url, array $options = [])
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($curl, CURLOPT_URL, $url);
        if (isset($options['headers'])) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $options['headers']);
        }
        curl_setopt($curl, CURLOPT_FAILONERROR, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HEADER, true);
        if (1 == strpos("$" . $url, "https://")) {
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        }
        if (isset($options['json'])) {
            curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($options['json']));
        } else {
            curl_setopt($curl, CURLOPT_POSTFIELDS, $options['body']);
        }

        $result      = curl_exec($curl);
        $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        $rheader     = substr($result, 0, $header_size);
        $rbody       = substr($result, $header_size);
        $httpCode    = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        return [
            'statusCode' => $httpCode,
            'body'       => json_decode($rbody, true)
        ];
    }
}
